using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Support.Javascript;
using Sedna.Util;
//using log4net;

namespace Sedna.Core.Controls.Support
{
	/// <summary>
	/// Summary description for BasePopupButton.
	/// </summary>
	[ValidationProperty("Text")]
	public abstract class BasePopupButton: BaseControl, INamingContainer, ILabelledControl, IClientScriptingControl, IPostBackDataHandler, IPostBackEventHandler
	{
	    
	    
        private static readonly object VALUE_CHANGED_EVENT = new object();
	    
//		private ILog log=LogManager.GetLogger(typeof(BasePopupButton));
		private bool postBackOnSelect=false;
		private bool causesValidation=false;

		protected string textKey;
		protected IList values;
        protected IList valueKeys;

        protected string popupParameters;
	    
		protected Control parameterControlsNamingContainer;
		protected Control displayControlsNamingContainer;

		protected bool resolveParameterControls=true;
		protected bool resolveDisplayControls=true;

		protected bool hookupParameterControlsEvents=true;

		protected HtmlInputButton popupButton = new HtmlInputButton();

		protected IDictionary parameterControls=new Hashtable();
		protected IDictionary displayControls=new Hashtable();

		private bool showUnnamed;
		private bool showInactive;


        public event EventHandler ValueChanged
        {
            add
            {
                Events.AddHandler(VALUE_CHANGED_EVENT, value);
            }
            remove
            {
                Events.RemoveHandler(VALUE_CHANGED_EVENT, value);
            }
        }
	    
        #region Properties

	    public string PopupParameters
	    {
	        get { return popupParameters; }
	        set { popupParameters = value; }
	    }

	    public new IPopupButtonConfiguration Configuration
	    {
            get { return (IPopupButtonConfiguration) base.Configuration; }
            set { base.Configuration = value; }
	    }
	    
		public bool ShowUnnamed
		{
			get { return showUnnamed; }
			set { showUnnamed = value; }
		}

		public bool ShowInactive
		{
			get { return showInactive; }
			set { showInactive = value; }
		}

		public string Text 
		{
			get { return popupButton.Value; }
			set { popupButton.Value = value; }
		}

		public string TextKey
		{
			get { return textKey; }
			set { textKey = value; }
		}

		public bool PostBackOnSelect
		{
			get { return postBackOnSelect; }
			set { postBackOnSelect = value; }
		}

		public bool CausesValidation
		{
			get { return causesValidation; }
			set { causesValidation = value; }
		}

	    public IList Values
	    {
	        get { return values; }
	    }

	    public IList ValueKeys
	    {
	        get { return valueKeys; }
	        set { valueKeys = value; }
	    }

	    public override bool Enabled
		{
			get { return base.Enabled; }
			set
			{
				base.Enabled = value;
				if (value)
				{
					popupButton.Attributes.Remove("disabled");	
				}
				else
				{
					popupButton.Attributes.Add("disabled", "disabled");
				}
				
			}
		}

	    /// <summary>
		/// Used to resolve parameter controls. Should be set, if parameter controls belong to 
		/// other NamingContainer, than popup button itself does.
		/// 
		/// For development purposes only.
		/// </summary>
		internal protected Control ParameterControlsNamingContainer
		{
			get { return parameterControlsNamingContainer ?? NamingContainer; }
			set { parameterControlsNamingContainer = value; }
		}

		/// <summary>
		/// Used to resolve display controls. Should be set, if display controls belong to 
		/// other NamingContainer, than popup button itself does.
		/// 
		/// For development purposes only.
		/// </summary>
		internal protected Control DisplayControlsNamingContainer
		{
			get { return displayControlsNamingContainer ?? NamingContainer; }
			set { displayControlsNamingContainer = value; }
		}

		internal protected bool ResolveParameterControls
		{
			get { return resolveParameterControls; }
			set { resolveParameterControls = value; }
		}

		protected internal bool ResolveDisplayControls
		{
			get { return resolveDisplayControls; }
			set { resolveDisplayControls = value; }
		}

		public bool HookupParameterControlsEvents
		{
			get { return hookupParameterControlsEvents; }
			set { hookupParameterControlsEvents = value; }
		}

		private IPopupButtonConfiguration PopupButtonConfiguration
		{
			get { return (IPopupButtonConfiguration) Configuration; }
		}


		public override bool ClientScriptingEnabled
		{
			get { return true;}
			set { /*Always enabled;*/ }
		}

		public IDictionary DisplayControls
		{
			get { return displayControls; }
			set
			{
				if (value==null)
				{
					displayControls=new Hashtable();
					return;
				}

				displayControls=value;
			}
		}

		public IDictionary ParameterControls
		{
			get { return parameterControls; }
			set
			{
				if (value==null)
				{
					parameterControls=new Hashtable();
					return;
				}
				parameterControls = value;
			}
		}

		private string ValuesContainerId
		{
			get { return ClientID+"_hiddenContainer";}
		}

		protected string PopupUrl
		{
			get { return ResolveUrl(PopupButtonConfiguration.PopupBase+PopupButtonConfiguration.PopupPage); }
		}

        #endregion
	    
	    
        public BasePopupButton(IConfiguration configuration) : base(configuration)
		{
            values = new ArrayList();
		}


		protected override void LoadViewState(object savedState)
		{
			base.LoadViewState(savedState);
			values=ViewState["values"] as IList;
		}

		protected override object SaveViewState()
		{
			ViewState["values"]=values;
			return base.SaveViewState();
		}


		public void RaisePostBackEvent(string eventArgument)
		{
			if (CausesValidation)
			{
                if (Configuration.ValidationGroup != null && !String.Empty.Equals(Configuration.ValidationGroup))
                {
                    Page.Validate(Configuration.ValidationGroup);
                } 
                else
                {
				    Page.Validate();
                }
				if (!Page.IsValid)
				{
					return;
				}
			}
			IExecutionContext executionContext=ExecutionContext.GetCurrent(ClientID);
			ControlUtil.ExecuteAction(executionContext, Context, Configuration, this.ClientID);
		}

	    protected virtual void OnValueChanged(EventArgs e)
	    {
            EventHandler handler = (EventHandler) Events[VALUE_CHANGED_EVENT];
	        if (handler!=null)
	        {
                handler(this, e);
	        }
	    }

		protected override void Build()
		{
			base.Build();
			this.TextKey = configuration.TextKey;

            ValueKeys = Configuration.ValueKeys;
			ClientScriptingEnabled=Configuration.ClientScriptingEnabled;
            ClientVariable = Configuration.ClientVariable;
            parameterControls = Configuration.ParameterControls;
            displayControls = Configuration.DisplayControls;
            PostBackOnSelect = Configuration.PostBackOnSelect;
            CausesValidation = Configuration.CausesValidation;
            hookupParameterControlsEvents = Configuration.HookupParameterControlsEvents;
            popupParameters = Configuration.PopupParameters;
		    if (Configuration.CssClass != null && !String.Empty.Equals(Configuration.CssClass))
			{
                popupButton.Attributes.Add("class", Configuration.CssClass);			
			}
		}

	    
	    
		public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
		{
		    IList oldValues = values;
		    values = new ArrayList(postCollection.GetValues(postDataKey));
		    if ((oldValues==null&&values.Count!=0)||(oldValues!=null&&values.Count!=oldValues.Count))
		    {
		        return true;
		    }
		    for (int i=0; i<values.Count; i++)
		    {
		        if (!Object.Equals(values[i], oldValues[i]))
		        {
		            return true;
		        }
		    }
			return false;
		}

		public virtual void RaisePostDataChangedEvent()
		{
		    OnValueChanged(EventArgs.Empty);    
		}

		protected override void CreateChildControls() 
		{         
			Controls.Add(popupButton);
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);
			Text=Configuration.GetLocalizedPostfixLabel(TextKey, Text);
			if (ClientScriptingEnabled)
			{
			    DeclareScriptVariable();
			}
		}

		protected override void RenderContents(HtmlTextWriter writer)
		{
			base.RenderContents(writer);
			writer.AddAttribute(HtmlTextWriterAttribute.Id, ValuesContainerId);
			writer.RenderBeginTag(HtmlTextWriterTag.Span);
			if (values!=null&&values.Count>0)
			{
				for (int i=0; i<values.Count; i++) 
				{
					RenderHidden(writer, (string)values[i]);
				}
			} 
			else
			{
				RenderHidden(writer, "");	
			}
			writer.RenderEndTag();
//			//To force LoadPostData call
//			RenderHidden(writer, "");
		}

		private void RenderHidden(HtmlTextWriter writer, string value)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID);
			writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
			writer.AddAttribute(HtmlTextWriterAttribute.Value, value);
			writer.RenderBeginTag(HtmlTextWriterTag.Input);
			writer.RenderEndTag();
		}

	    protected override void DeclareScriptVariable()
	    {
	        base.DeclareScriptVariable();
            popupButton.Attributes.Add("onclick", String.Format("{0}.onclick()", ClientVariable));

	    }

	    protected override IDictionary BuildScriptParameters()
	    {
	        IDictionary parameters =  base.BuildScriptParameters();
            parameters.Add("config", "config="+JavascriptUtil.ToScriptObject(BuildConfigParameters()));
            return parameters;
	    }

	    protected virtual IDictionary BuildConfigParameters()
		{
			IDictionary parameters=new Hashtable(15);
	        parameters.Add("valueKeys", new object[]{"id"});
            parameters.Add("controlVar", ClientVariable);
			parameters.Add("uniqueId", UniqueID);
			parameters.Add("buttonId", popupButton.ClientID);
			parameters.Add("hiddenContainerId", ValuesContainerId);
            parameters.Add("displayControls", new ScriptObject("Map", JavascriptUtil.Serialize(ResolveDisplayControls ? ControlUtil.ResolveClientScriptingControls(DisplayControls, DisplayControlsNamingContainer) : DisplayControls, ";", "=")));
            parameters.Add("parameterControls", new ScriptObject("Map", JavascriptUtil.Serialize(ResolveParameterControls ? ControlUtil.ResolveClientScriptingControls(ParameterControls, ParameterControlsNamingContainer) : ParameterControls, ";", "=")));
			parameters.Add("popup", new ScriptObject("Popup", PopupUrl, PopupButtonConfiguration.PopupWidth, PopupButtonConfiguration.PopupHeight));
			parameters.Add("popupParameters", popupParameters+(showUnnamed?";showUnnamed=Y":String.Empty)+(";showInactive="+(showInactive?'Y':'N')));
			parameters.Add("doPostBack", PostBackOnSelect);
			parameters.Add("postBackScript", HttpUtility.HtmlAttributeEncode(Page.ClientScript.GetPostBackEventReference(this, String.Empty)));
			parameters.Add("hookupParameterControlsEvents", hookupParameterControlsEvents);
			return parameters;
		}


	}

}
